package api

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strconv"
    "time"

    "github.com/we-pay-kit/we-pay-kit/internal/db"
    "github.com/we-pay-kit/we-pay-kit/internal/repository"
)

type ReconSettleHandler struct {
    trxRepo *repository.TransactionRepository
    reconRepo *repository.ReconciliationRepository
    settleRepo *repository.SettlementRepository
}

func NewReconSettleHandler() *ReconSettleHandler {
    database := db.GetDB()
    return &ReconSettleHandler{trxRepo: repository.NewTransactionRepository(database), reconRepo: repository.NewReconciliationRepository(database), settleRepo: repository.NewSettlementRepository(database)}
}

// POST /api/v1/reconciliation/run?date=2025-09-01 (简单按日期聚合交易数据)
func (h *ReconSettleHandler) RunReconciliation(w http.ResponseWriter, r *http.Request) {
    dateStr := r.URL.Query().Get("date")
    if dateStr == "" { http.Error(w, "missing date", http.StatusBadRequest); return }
    date, err := time.Parse("2006-01-02", dateStr); if err != nil { http.Error(w, "invalid date", http.StatusBadRequest); return }
    // 简化：直接汇总 transaction_record 当日数据（此处省略SQL聚合实现，示例设置为0）
    data := repository.ReconciliationData{ReconciliationDate: date, TotalTransactionCount: 0, TotalTransactionAmount: 0, TotalDiscountAmount: 0, TotalActualPayAmount: 0, ReconStatus: "UNCHECKED"}
    if err := h.reconRepo.Upsert(r.Context(), data); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError); return }
    _ = json.NewEncoder(w).Encode(map[string]any{"status": "ok", "date": dateStr})
}

// POST /api/v1/settlements/create  (生成结算单)
func (h *ReconSettleHandler) CreateSettlement(w http.ResponseWriter, r *http.Request) {
    var in struct{
        SettlementNo     string  `json:"settlement_no"`
        SettlementPeriod string  `json:"settlement_period"`
        TotalAmount      float64 `json:"total_amount"`
        ServiceFeeRate   float64 `json:"service_fee_rate"`
        SettlementType   string  `json:"settlement_type"`
    }
    if err := json.NewDecoder(r.Body).Decode(&in); err != nil { http.Error(w, err.Error(), http.StatusBadRequest); return }
    fee := in.TotalAmount * in.ServiceFeeRate
    actual := in.TotalAmount - fee
    order := &repository.SettlementOrder{SettlementNo: in.SettlementNo, SettlementPeriod: in.SettlementPeriod, TotalAmount: in.TotalAmount, ServiceFeeRate: in.ServiceFeeRate, ServiceFeeAmount: fee, ActualSettlementAmount: actual, SettlementType: in.SettlementType, Status: "PENDING"}
    id, err := h.settleRepo.CreateOrder(r.Context(), order)
    if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError); return }
    _ = json.NewEncoder(w).Encode(map[string]any{"id": id, "settlement_no": in.SettlementNo})
}

// POST /api/v1/settlements/add-detail
func (h *ReconSettleHandler) AddSettlementDetail(w http.ResponseWriter, r *http.Request) {
    var in struct{
        SettlementID int64   `json:"settlement_id"`
        ActivityID   int64   `json:"activity_id"`
        ActivityName string  `json:"activity_name"`
        TransactionCount int `json:"transaction_count"`
        TotalAmount  float64 `json:"total_amount"`
        DiscountAmount float64 `json:"discount_amount"`
    }
    if err := json.NewDecoder(r.Body).Decode(&in); err != nil { http.Error(w, err.Error(), http.StatusBadRequest); return }
    d := &repository.SettlementDetail{SettlementID: in.SettlementID, ActivityID: in.ActivityID, ActivityName: in.ActivityName, TransactionCount: in.TransactionCount, TotalAmount: in.TotalAmount, DiscountAmount: in.DiscountAmount}
    id, err := h.settleRepo.AddDetail(r.Context(), d)
    if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError); return }
    _ = json.NewEncoder(w).Encode(map[string]any{"id": id})
}

// PATCH /api/v1/settlements/status?settlement_no=xxx&status=COMPLETED
func (h *ReconSettleHandler) UpdateSettlementStatus(w http.ResponseWriter, r *http.Request) {
    q := r.URL.Query()
    no := q.Get("settlement_no")
    st := q.Get("status")
    if no == "" || st == "" { http.Error(w, "missing params", http.StatusBadRequest); return }
    if err := h.settleRepo.UpdateStatus(r.Context(), no, st); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError); return }
    w.WriteHeader(http.StatusNoContent)
}

// GET /api/v1/reconciliation/data?date=2025-09-01
func (h *ReconSettleHandler) GetReconciliation(w http.ResponseWriter, r *http.Request) {
    dateStr := r.URL.Query().Get("date")
    date, err := time.Parse("2006-01-02", dateStr); if err != nil { http.Error(w, "invalid date", http.StatusBadRequest); return }
    d, err := h.reconRepo.GetByDate(r.Context(), date)
    if err != nil { http.Error(w, fmt.Sprintf("not found: %v", err), http.StatusNotFound); return }
    _ = json.NewEncoder(w).Encode(d)
}

// GET /api/v1/settlements/get?settlement_no=xxx  获取结算单
func (h *ReconSettleHandler) GetSettlement(w http.ResponseWriter, r *http.Request) {
    no := r.URL.Query().Get("settlement_no")
    if no == "" { http.Error(w, "missing settlement_no", http.StatusBadRequest); return }
    o, err := h.settleRepo.GetByNo(r.Context(), no)
    if err != nil { http.Error(w, fmt.Sprintf("not found: %v", err), http.StatusNotFound); return }
    _ = json.NewEncoder(w).Encode(o)
}

// GET /api/v1/settlements/list?limit=&offset=
func (h *ReconSettleHandler) ListSettlements(w http.ResponseWriter, r *http.Request) {
    q := r.URL.Query()
    limit, _ := strconv.Atoi(q.Get("limit"))
    offset, _ := strconv.Atoi(q.Get("offset"))
    list, err := h.settleRepo.ListOrders(r.Context(), limit, offset)
    if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError); return }
    _ = json.NewEncoder(w).Encode(list)
}

// GET /api/v1/settlements/details?settlement_id=&limit=&offset=
func (h *ReconSettleHandler) ListSettlementDetails(w http.ResponseWriter, r *http.Request) {
    q := r.URL.Query()
    sid, _ := strconv.ParseInt(q.Get("settlement_id"), 10, 64)
    if sid == 0 { http.Error(w, "missing settlement_id", http.StatusBadRequest); return }
    limit, _ := strconv.Atoi(q.Get("limit"))
    offset, _ := strconv.Atoi(q.Get("offset"))
    list, err := h.settleRepo.ListDetailsBySettlement(r.Context(), sid, limit, offset)
    if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError); return }
    _ = json.NewEncoder(w).Encode(list)
}


